<!DOCTYPE HTML>
<html lang="zh_CN" class="sidebar-visible no-js light">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>系统托盘 - Lithium 双引擎 v0.0.1</title>
        <!-- Custom HTML head -->
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        <link rel="icon" href="../favicon.svg">
        <link rel="shortcut icon" href="../favicon.png">
        <link rel="stylesheet" href="../css/variables.css">
        <link rel="stylesheet" href="../css/general.css">
        <link rel="stylesheet" href="../css/chrome.css">
        <link rel="stylesheet" href="../css/print.css" media="print">
        <!-- Fonts -->
        <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../fonts/fonts.css">
        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../highlight.css">
        <link rel="stylesheet" href="../tomorrow-night.css">
        <link rel="stylesheet" href="../ayu-highlight.css">

        <!-- Custom theme stylesheets -->
    </head>
    <body>
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded "><a href="../intro.html"><strong aria-hidden="true">1.</strong> 简介</a></li><li class="chapter-item expanded "><a href="../Upgrade.html"><strong aria-hidden="true">2.</strong> 从单引擎迁移</a></li><li class="chapter-item expanded "><a href="../basic.html"><strong aria-hidden="true">3.</strong> 基本用法</a></li><li class="chapter-item expanded "><a href="../web/web.html"><strong aria-hidden="true">4.</strong> 网页接口</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../web/dev-tools.html"><strong aria-hidden="true">4.1.</strong> 开发者工具</a></li><li class="chapter-item expanded "><a href="../web/env.html"><strong aria-hidden="true">4.2.</strong> env</a></li><li class="chapter-item expanded "><a href="../web/exit.html"><strong aria-hidden="true">4.3.</strong> exit</a></li><li class="chapter-item expanded "><a href="../web/main-window.html"><strong aria-hidden="true">4.4.</strong> MainWindow 类</a></li><li class="chapter-item expanded "><a href="../web/open-window.html"><strong aria-hidden="true">4.5.</strong> 打开窗口</a></li><li class="chapter-item expanded "><a href="../web/plugins.html"><strong aria-hidden="true">4.6.</strong> 插件</a></li><li class="chapter-item expanded "><a href="../web/struct-type.html"><strong aria-hidden="true">4.7.</strong> ctype</a></li><li class="chapter-item expanded "><a href="../web/shell.html"><strong aria-hidden="true">4.8.</strong> 运行本地脚本</a></li><li class="chapter-item expanded "><a href="../web/tray-icon.html" class="active"><strong aria-hidden="true">4.9.</strong> 系统托盘</a></li></ol></li><li class="chapter-item expanded "><a href="../cmdline.html"><strong aria-hidden="true">5.</strong> 命令行参数</a></li><li class="chapter-item expanded "><a href="../runtime.html"><strong aria-hidden="true">6.</strong> 运行时</a></li><li class="chapter-item expanded "><a href="../crash-report.html"><strong aria-hidden="true">7.</strong> 崩溃报告</a></li><li class="chapter-item expanded "><a href="../transparent-window.html"><strong aria-hidden="true">8.</strong> 透明窗口</a></li><li class="chapter-item expanded "><a href="../preferences.html"><strong aria-hidden="true">9.</strong> Preferences 配置文件</a></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky bordered">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">Lithium 双引擎 v0.0.1</h1>

                    <div class="right-buttons">
                        <a href="../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>
                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>
                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="系统托盘"><a class="header" href="#系统托盘">系统托盘</a></h1>
<h2 id="新引擎有关托盘的使用逻辑"><a class="header" href="#新引擎有关托盘的使用逻辑">新引擎有关托盘的使用逻辑</a></h2>
<p>主窗口创建托盘，然后绑定托盘事件。
托盘事件的绑定由用户自定义，一般使用场景是：左键点击控制主窗口是的显示隐藏，右键点击控制右键菜单窗口的显示隐藏。
右键菜单窗口由用户定义确认，本质上和其它窗口页面的创建和使用没有区别。</p>
<p>新引擎都是通过 lnks.MainWindow.all(); 获取所有窗口后，遍历出自己所需的窗口而后加以操作的，这种方式是由<code>chrome</code> 引擎以及<code>双引擎</code>窗口关系结构决定的。</p>
<p>创建托盘时遵循以下原则：
1、<code>new lnks.TrayIcon(&quot;IconAccessPath&quot;)</code> 中 <code>IconAccessPath</code> 是可选参数，不传递该参数时，使用默认图标(gecko/default.ico)。
2、传递 <code>IconAccessPath</code> 时，引擎会先下载图标，下载过程会阻塞后续的程序运行。下载失败则不会创建托盘，下载如果需要 10 秒则需要 10 秒后才创建托盘。
3、传递 图标 <code>Base64</code> 数据。新引擎提供了该托盘创建方式，使用该方式可以达到网络异常和本地不可定制之间的平衡。</p>
<h2 id="双引擎托盘创建实例"><a class="header" href="#双引擎托盘创建实例">双引擎托盘创建实例</a></h2>
<p>待功能实现后补充完整</p>
<pre><code class="language-javascript">// 托盘创建
this.trayIcon = new window.lnks.TrayIcon(window, iconUrl);
// 托盘事件绑定
this.trayIcon.onMenuPopup = () =&gt; console.log(`onMenuPopup()`);
this.trayIcon.onActivate = () =&gt; console.log(`onActivate()`);
// 托盘销毁
this.trayIcon.destroy();
this.trayIcon = null;
// 托盘位置获取(用以辅助控制右键菜单窗口的位置)
let geometry = this.trayIcon.geometry;
console.log(&quot;geometry:&quot;, geometry);
</code></pre>
<p>由于部分操作系统在激活前无法获取到托盘所在位置，因此强烈建议您在做依赖托盘坐标的动作时，与托盘的点击(激活)事件进行绑定。</p>
<p>如下进行右键菜单的操作：</p>
<pre><code class="language-javascript">// 创建托盘
window.trayIcon = new lnks.TrayIcon(window); // chromium has no remote ico feat
let g = window.trayIcon.geometry;
let width = 100;
let height = 210;
console.log(&quot;g:&quot;, g);
console.log(&quot;p:&quot;, g.x - 100 / 2, g.y - height);
let winArg = {
  url: &quot;./apps/popup.html&quot;,
  appId: &quot;trayWin&quot;,
  skipBar: true,
  width: width,
  height: height,
  // &quot;positionX&quot;: 0 - width,
  // &quot;positionY&quot;: 0 - height,
  hideChrome: true,
  winMode: &quot;normal&quot;,
  hidden: true,
  useGecko: win.isGecko()
};
// 创建托盘菜单页面
lnks.openWindow2(winArg, {});
console.log(`lnks.openWindow2(${JSON.stringify(winArg)}, {});`);

// 绑定鼠标左键点击事件
trayIcon.onActivate = () =&gt; {
  console.log(&quot;activate&quot;);
  window.win.visibility = !window.win.visibility;
};
// 绑定鼠标右键点击事件(点击时获取坐标)
trayIcon.onMenuPopup = () =&gt; {
  if (!window.trayWin) {
    window.trayWin = getLnksWin({appId: &quot;trayWin&quot;}, true);
  }
  let height=200
  console.log(&quot;size1:&quot;, JSON.stringify(trayWin.size));
  console.log(&quot;tray.visibily:&quot;, JSON.stringify(trayWin.visibily));
  if (trayWin.visibility) {
    //trayWin.setSize(1,1)//UOS设置无效
    trayWin.visibility = false;
    console.log(&quot;size2:&quot;, JSON.stringify(trayWin.size));
  } else {
    // UOS 系统没有显示时不能改位置，显示时可以改位置但是不能超出屏幕
    let g = this.trayIcon.geometry;
    console.log(&quot;g:&quot;, JSON.stringify(g));
    // devicePixelRatio 屏幕缩放比例
    let px = parseInt((g.x - 100/2)/devicePixelRatio);
    let py = parseInt((g.y - height)/devicePixelRatio);
    console.log(&quot;p:&quot;, px, py);
    trayWin.setSize(1,1);
    trayWin.visibility = true;
    trayWin.setPosition(px, py);
    trayWin.setSize(100,200)
  }
};
</code></pre>
<h2 id="老引擎的托盘创建实例"><a class="header" href="#老引擎的托盘创建实例">老引擎的托盘创建实例</a></h2>
<p>主页面 主动创建系统托盘</p>
<pre><code class="language-javascript">// 初始化一个托盘图标
this.trayIcon = new lnks.TrayIcon(window, &quot;./nazha.ico&quot;); // 一个托盘实例对象
this.lnksWin = new window.lnks.MainWindow(window); // 主窗口当前对象

// 创建托盘菜单页
// setTimeout 不是必须的
// 在有些运算力弱的机器上 初始化托盘图标可能需要一点时间。
setTimeout(() =&gt; {
  let g = this.trayIcon.geometry; // 获取创建好的托盘位置
  let width = 100;
  let height = 200;
  console.log(&quot;g:&quot;, g);
  console.log(&quot;p:&quot;, g.x - width / 2, g.y - height); // 根据托盘位置计算页面位置
  lnks.openWindow2(
    {
      url: &quot;./popup.html&quot;,
      // &quot;skip_bar&quot;: true,
      skipBar: true,
      width: width,
      height: height,
      positionX: g.x - width / 2,
      positionY: g.y - height,
      hideChrome: true,
      hidden: true
    },
    {
      // &quot;HomeWindow&quot;: this.lnksWin, // 打开页面的 window.arguments.HomeWindow
      // &quot;TrayIcon&quot;: this.trayIcon, // 打开页面的 window.arguments.TrayIcon
    }
  );
}, 1000);

// 销毁托盘
function delTray() {
  if (this.trayIcon) {
    // 确认创建托盘实例对象
    this.trayIcon.destroy();
  } else {
    console.error(&quot;TrayIcon not created&quot;);
  }
}
</code></pre>
<p>托盘右键菜单页</p>
<pre><code class="language-html">&lt;lnks_app&gt;&lt;/lnks_app&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;托盘&lt;/title&gt;
  &lt;/head&gt;
  &lt;style&gt;
    * {
      margin: 0;
      padding: 0;
    }
    .tray-container {
      background: rgba(0, 0, 0 0);
      width: 100%;
      position: absolute;
      bottom: 0;
    }
    .tray-container button {
      width: 100%;
      height: 30px;
      padding: auto;
      margin: auto;
      text-align: center;
    }
  &lt;/style&gt;
  &lt;body&gt;
    &lt;div class=&quot;tray-container&quot;&gt;
      &lt;button onclick=&quot;location.reload()&quot;&gt;刷新&lt;/button&gt;
      &lt;button onclick=&quot;lnks.DevTools.toggle(window)&quot;&gt;调试&lt;/button&gt;
      &lt;button onclick=&quot;lnks.exit()&quot;&gt;退出程序&lt;/button&gt;
    &lt;/div&gt;
  &lt;/body&gt;
  &lt;script&gt;
    window.onload = function () {
      if (window.lnks &amp;&amp; window.arguments) {
        // 获取主窗口Window实例
        let hw = window.arguments.HomeWindow; // 打开本窗口时传递过来的参数
        let tray = window.arguments.TrayIcon; // 打开本窗口时传递过来的参数
        this.win = new window.lnks.MainWindow(window); // 当前右键菜单窗口实例化对象
        win.setSize(100, 250);
        win.skip_bar(); //本窗口跳过任务栏
        win.keep_above(); //保持置顶
        win.visibility = false; //初始化时隐藏界面
        window.onclose = (e) =&gt; {
          var r = confirm(&quot;确定要退出吗?&quot;);
          if (r) {
            //nothing
          } else {
            e.preventDefault();
          }
        };
        onblur = (e) =&gt; {
          //失去焦点时隐藏本窗口
          console.info(&quot;失去焦点:onblur&quot;);
          win.visibility = false;
          return true;
        };
        onclick = () =&gt; {
          //任何点击事件后都隐藏窗口，这个可以根据应用逻辑自行调整。
          console.info(&quot;点击事件:onclick&quot;);
          win.visibility = false;
          return true;
        };

        //trayicon的鼠标右键处理逻辑
        tray.onMenuPopup = (a, b) =&gt; {
          console.info(&quot;右键:onMenuPopup:a&quot;, a);
          console.info(&quot;右键:onMenuPopup:b&quot;, b);
          console.info(&quot;右键:onMenuPopup:b&quot;, this.win.visibility);
          if (!this.win.visibility) {
            this.win.visibility = true;
            window.focus(); //强制获取焦点
          } else {
            this.win.visibility = false;
          }
        };

        if (hw) {
          //主窗口关闭或刷新时候销毁trayicon以及关闭本窗口。
          hw.win.addEventListener(&quot;unload&quot;, function (tray) {
            if (tray) {
              tray.destroy();
            }
            this.win.close();
          });
        }

        //trayicon的鼠标左键处理逻辑
        tray.onActivate = function (a, b) {
          console.info(&quot;左键:onActivate:a&quot;, a);
          console.info(&quot;左键:onActivate:b&quot;, b);
          if (hw) {
            hw.visibility = true;
            hw.minimize();
            hw.win.focus(); // win7 激活的窗口没有出现在最顶层
          } else {
            this.win.minimize();
          }
        };
      } else {
        alert(&quot;浏览器不支持本Demo&quot;);
      }
    };
  &lt;/script&gt;
&lt;/html&gt;
</code></pre>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../web/shell.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>
                            <a rel="next" href="../cmdline.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>
                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../web/shell.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                    <a rel="next" href="../cmdline.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>

        <script type="text/javascript">
            window.playground_copyable = true;
        </script>
        <script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
        <script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="../book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->
    </body>
</html>
